package com.ruan.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruan.common.Code;
import com.ruan.common.Result;
import com.ruan.mapper.*;
import com.ruan.pojo.*;
import com.ruan.pojoExt.*;
import com.ruan.service.*;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@CrossOrigin
@RequestMapping("/project")
public class ProjectController {
    @Autowired
    private ProjectService projectService;
    @Autowired
    PositionService positionService;
    @Autowired
    private ClientService clientService;
    @Autowired
    private ClientMapper clientMapper;
    @Autowired
    private ProjectMapper projectMapper;
    @Autowired
    private EmployeeService employeeService;
    @Autowired
    private EmployeeMapper employeeMapper;
    @Autowired
    private DepartmentService departmentService;
    @Autowired
    private ParticipantMapper participantMapper;
    @Autowired
    private ParticipantService participantService;
    @Autowired
    private SalaryService salaryService;
//    @Autowired
//    private SalarySetService salarySetService;
    @Autowired
    private SalarySetMapper salarySetMapper;
    @Autowired
    private ToolsService toolsService;
    @Autowired
    private ProjectToolAssignmentMapper projectToolAssignmentMapper;

    //项目信息分页查询
    //创建一个controller方法，接收页面发送的请求并且接收参数（page,pageSize,name）
    @PostMapping("/page/{currentPage}/{pageSize}")
    @ApiOperation(value = "项目信息分页查询接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "currentPage", value = "页码", required = true, paramType = "path", dataType = "int"),
            @ApiImplicitParam(name = "pageSize", value = "每页记录数", required = true, paramType = "path", dataType = "int"),
            @ApiImplicitParam(name = "queryProjectCondition", value = "项目信息查询条件", required = false, paramType = "body",
                    dataType = "QueryProjectCondition")
    })
    @Cacheable(value = "projectCache",
            key = "#currentPage + '_' " +
                    "+ #pageSize + '_' " +
                    "+ #queryProjectCondition",
            unless = "#result == null")
    public Result page(@PathVariable int currentPage,
                       @PathVariable int pageSize,
                       @RequestBody QueryProjectCondition queryProjectCondition){//, String cname第三个参数 name 可能是从前端的用户输入或者页面的搜索框中获取的
//        System.out.println("project的page传来的参数是："+currentPage+pageSize+queryProjectCondition);
        Page<Project> iPage=new Page<>(currentPage,pageSize);
        LambdaQueryWrapper<Project> queryWrapper = new LambdaQueryWrapper();
//        System.out.println("getProjectName是null还是''："+queryProjectCondition.getProjectName());
        queryWrapper.like(!queryProjectCondition.getProjectName().equals(""),
                Project::getProjectName,queryProjectCondition.getProjectName());//!=null,
        //部门下拉框搜索
//        System.out.println("getDepartmentId是null还是''："+queryProjectCondition.getDepartmentId());
        queryWrapper.eq(queryProjectCondition.getDepartmentId()!=null,
                Project::getDepartmentId,queryProjectCondition.getDepartmentId());

        //客户名字输入模糊搜索
        LambdaQueryWrapper<Client> queryWrapper1 = new LambdaQueryWrapper();
//        System.out.println("getClientName是null还是''："+queryProjectCondition.getClientName());
        queryWrapper1.like(!queryProjectCondition.getClientName().equals(""),
                Client::getName,queryProjectCondition.getClientName());//!=null,
        List<Client> clientList = clientMapper.selectList(queryWrapper1);
        List<Long> clientIds = clientList.stream().map(Client::getId).collect(Collectors.toList());
        queryWrapper.in(Project::getClientId, clientIds);
        //负责人名字输入模糊搜索，可能是空
        LambdaQueryWrapper<Employee> queryWrapper2 = new LambdaQueryWrapper();
//        System.out.println("getEmployeeName是null还是''："+queryProjectCondition.getEmployeeName());
        queryWrapper2.like(!queryProjectCondition.getEmployeeName().equals(""),
                Employee::getName,queryProjectCondition.getEmployeeName());
        //在MyBatis中，如果queryWrapper2是null或者空字符串，employeeMapper.selectList(queryWrapper2)将会
        // 获取Employee表中的所有记录。当queryWrapper2为null时，MyBatis会忽略这个条件，因此会返回整个表中的数据。
        // 如果queryWrapper2是空字符串，MyBatis也会将其视为没有附加条件，同样会返回整个表中的数据
//根据项目负责人搜索
//        System.out.println("queryWrapper2是空的吗："+queryWrapper2);
//        List<Employee> employeeList = employeeMapper.selectList(queryWrapper2);
//
//        System.out.println("employeeList有什么："+employeeList);
//        List<Long> employeeIds = employeeList.stream().map(Employee::getId).collect(Collectors.toList());
//        System.out.println("employeeIds是什么："+employeeIds);

//        employeeIds.add(null); // 添加空值，Project表里可能有一些记录的EmployeeId是空值，让IN也可以找到他
        //没有负责人时不显示，分配了负责人之后再显示？？？？？？
//        queryWrapper.in(!employeeIds.equals(""),Project::getEmployeeId, employeeIds.toArray()).or().isNull(Project::getEmployeeId);
        //项目完成状态下拉框搜索
//        System.out.println("getCompletionStatus是null还是''："+queryProjectCondition.getCompletionStatus());

        queryWrapper.like(!queryProjectCondition.getCompletionStatus().equals(""),
                Project::getCompletionStatus,queryProjectCondition.getCompletionStatus());//!=null,
        //项目支付状态下拉框搜索
//        System.out.println("getPayStatus是null还是''："+queryProjectCondition.getPayStatus());
        queryWrapper.eq(!queryProjectCondition.getPayStatus().equals(""),
                Project::getPayStatus,queryProjectCondition.getPayStatus());//!=null,

        Page<ProjectExt> iPageExt = new Page<>();
//----------------------------------------------
        queryWrapper.orderByDesc(Project::getCreateTime);
        //防止：分页查询时，限制每页记录条数为4条，第一页先按客户id: 1，2，3，4顺序查到第1，2，3，5条数据，
        // 因为数据库中顺序数下来的第5条数据的clientId是3，而数据库中顺序数下来第四条数据的clientId是4，
        // 在前端点击下一页按钮时，却只显示数据库中顺序数下来的第5条数据，而数据库中顺序数下来第四条数据就是不显示。
        projectService.page(iPage,queryWrapper);//page方法已经已经继承了IService,已经提供了分页查询方法，只需要把Page对象和queryWrapper对象构造好，传给他，自己就会进行分页查询

        BeanUtils.copyProperties(iPage,iPageExt,"records");//从pageInfo一个一个拷贝属性到projectExtPage上(除了records)
        //处理
        List<Project> records = iPage.getRecords();
        List<ProjectExt> list = records.stream().map((item) -> {//item:遍历出来的每一个项目对象
            ProjectExt projectExt = new ProjectExt();//只有ProjectExt符合项目管理页面的要求，所以new一个出来,进行填充
            BeanUtils.copyProperties(item,projectExt);//先填充入project的普通属性
            Long clientId = item.getClientId();//拿到了每个项目所对应的项目客户id
            Long departmentId = item.getDepartmentId();//拿到了每个项目所对应的部门id
            Long employeeId = item.getEmployeeId();//拿到了每个项目所对应的负责人id

            if(employeeId != null){//负责人可以为空，项目经理都有了，说明组员也有了
              LambdaQueryWrapper<Participant> queryWrapper3 = new LambdaQueryWrapper<>();
             queryWrapper3.eq(Participant::getProjectId,item.getId());
             List<Participant> participantList = participantMapper.selectList(queryWrapper3);
            //就可以数一数项目的参与人数
                int employeeNum = participantList.size();
                if(participantList != null){
                    projectExt.setEmployeeNum(employeeNum);
                    //必须有项目经理，把项目经理也加入到partic表，不需要，因为选择项目经理之后，
                    // 项目经理同时也会添加到参与人员中
                }
                Employee employee = employeeService.getById(employeeId);
                if(employee != null){//能查到项目的负责人
                    projectExt.setEmployeeName(employee.getName());//填充入projects没有的clientName属性
                }
            }

           if (item != null && item.getActualAmount() != null
                   && item.getActualCost() != null
                   && item.getTax() != null) {
               //利润 = 收入 - 成本
//            BigDecimal preProrofit = item.getActualAmount() - item.getActualCost();
               BigDecimal preProfit = item.getActualAmount().subtract(item.getActualCost());

               //税后利润 = 利润 * (1 - 税率)
//            BigDecimal profit = preProfit * (1-item.getTax())
               BigDecimal profit = preProfit.multiply(BigDecimal.ONE.subtract(item.getTax()));

               item.setProfit(profit);
               System.out.println("profit利润计算："+profit);
               //更新到数据库
               projectMapper.updateById(item);
           }
            //根据clientId查客户(表)(需要注入clientService)，把clientName拿到
            Client client = clientService.getById(clientId);
            Department department = departmentService.getById(departmentId);

            if(client != null){//能查到项目的客户
                projectExt.setClientName(client.getName());//填充入projects没有的clientName属性
            }

            if(department != null){//能查到项目的客户
                projectExt.setDepartmentName(department.getName());//填充入projects没有的clientName属性
            }else {//如果添加项目时没写项目归属，就默认是属于负责人的部门
                Employee employee = employeeService.getById(employeeId);
                if(employee != null){
                    Department department1 = departmentService.getById(employee.getDepartmentId());
                    projectExt.setDepartmentName(department1.getName());
                }
            }

            return projectExt;//填充完新键的projectExt之后，返回，把遍历的这些projectExt对象搜集起来后
        }).collect(Collectors.toList());//就转成集合了，赋给List<projectExt> list
        System.out.println("list里有了什么"+list);//.toString()
        iPageExt.setRecords(list);//list获得了改造过后的projectExt集合之后，被用来设置page对象的Records属性
        return new Result(Code.SELECT_OK,iPageExt);
    }

    //不分页获取个人负责的项目
    @PostMapping("/page")
    public Result page(@RequestParam("employeeId") String employeeId){
        LambdaQueryWrapper<Project> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Project::getEmployeeId,employeeId);
        List<Project> projectList = projectMapper.selectList(queryWrapper);
        List<ProjectExt> projectExtList = new ArrayList<>();
        for(Project project : projectList){
            ProjectExt projectExt = new ProjectExt();
            BeanUtils.copyProperties(project,projectExt);

            Client client = clientService.getById(project.getClientId());
            projectExt.setClientName(client.getName());

            Department department = departmentService.getById(project.getDepartmentId());
            projectExt.setDepartmentName(department.getName());

            LambdaQueryWrapper<Participant> queryWrapper1 = new LambdaQueryWrapper<>();
            queryWrapper1.eq(Participant::getProjectId,project.getId());
            List<Participant> participantList = participantMapper.selectList(queryWrapper1);
            //就可以数一数项目的参与人数
            int employeeNum = participantList.size();
            if(participantList != null) {
                projectExt.setEmployeeNum(employeeNum);//显示参与人数
            }
            projectExtList.add(projectExt);
        }

        if(projectExtList.isEmpty()){
            return new Result(Code.SELECT_ERR,"个人负责项目查询失败");
        }
        return new Result(Code.SELECT_OK,projectExtList,"个人负责项目查询成功");
    }

    @GetMapping("/exportToExcel")
    public ResponseEntity<byte[]> exportToExcel(){
        try {
            byte[] excelBytes = projectService.exportToExcel();

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"));
            headers.setContentDispositionFormData("attachment", "项目表.xlsx");

            return ResponseEntity.ok()
                    .headers(headers)
                    .body(excelBytes);
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
        }
    }

    @GetMapping("/deleteProject/{id}")
    public Result deleteProject(@PathVariable Integer id){
        System.out.println("deleteProject传来的id是"+id);
        if (projectService.deleteProject(id)){
            return new Result(Code.UPDATE_OK,"项目删除成功！");
        }
        return new Result(Code.UPDATE_ERR,"项目删除失败！");
    }

    @GetMapping("/deadline/{projectId}")
    public Result getProjectDeadline(@PathVariable Long projectId) {

            System.out.println("前端传来的projectId是"+projectId);
            LambdaQueryWrapper<Project> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.select(Project::getEndDate).eq(Project::getId,projectId);
            Project project = projectMapper.selectOne(queryWrapper);
            if(project!=null){
                return new Result(Code.SELECT_OK,project,"项目截止日期获取成功");
            }
            return new Result(Code.SELECT_ERR,"项目截止日期获取失败");

    }

   //检查有没有待分配的项目
    @GetMapping("/checkPendingTasks")
    public Result checkTodayTasks(@RequestParam String employeeId) {
        List<ProjectExt> projectExtList = projectService.getTodayProjects(employeeId);
        if(projectExtList.isEmpty()){//isEmpty() ???
            return new Result(Code.SELECT_ERR,"今日项目查找失败");
        }
        return new Result(Code.SELECT_OK,projectExtList,"今日项目查找成功");

    }

    @GetMapping("/checkExistence/{id}")//不能删除正在合作的客户
    public Result checkExistence(@PathVariable Integer id){
        System.out.println("checkExistence传来的(客户)id是"+id);
       LambdaQueryWrapper<Project> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Project::getClientId,id);
        List<Project> projectList = projectMapper.selectList(queryWrapper);
        if (!projectList.isEmpty()){
            return new Result(Code.SELECT_OK,"该客户合作中！");
        }
        return new Result(Code.SELECT_ERR,"该客户未合作！");
    }

    /**
     * 根据项目id查询单个项目资源利用的详细记录
     * @param projectId 查询条件：项目id
     * @return
     */
    @PostMapping("/getProjectDetailInfo")
    public Result getProjectDetailInfo(@RequestParam("projectId") String projectId){
        System.out.println("传过来的项目id为："+projectId);
        Project project = projectService.getById(projectId);
        LambdaQueryWrapper<Participant> participantWrapper = new LambdaQueryWrapper<>();
        LambdaQueryWrapper<ProjectToolAssignment> projectToolAssignmentWrapper = new LambdaQueryWrapper<>();
        participantWrapper.eq(Participant::getProjectId,projectId);
        projectToolAssignmentWrapper.eq(ProjectToolAssignment::getProjectId,projectId);

        List<Participant> participantList = participantMapper.selectList(participantWrapper);
        List<ProjectToolAssignment> projectToolAssignmentList = projectToolAssignmentMapper.selectList(projectToolAssignmentWrapper);

        ProjectResourceExt projectResourceExt = new ProjectResourceExt();
        System.out.println("属性搬前："+project);
        BeanUtils.copyProperties(project,projectResourceExt);
        System.out.println("属性搬完了吗："+projectResourceExt);

        //根据项目id查询到了这个项目用到什么人
//        List<Employee> employees = new ArrayList<>();
        BigDecimal totalOriginalPay = BigDecimal.ZERO; // 初始化累加变量为0
        List<EmployeeExt> employeesExt = new ArrayList<>();
        for(Participant participant : participantList){
           Employee employee = employeeService.getById(participant.getEmployeeId());
            EmployeeExt employeeExt = new EmployeeExt();
            BeanUtils.copyProperties(employee,employeeExt);
//            Salary salary = salaryService.getById(employee.getId());//经典id错
            LambdaQueryWrapper<SalarySet> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(SalarySet::getEmployeeId,employee.getId());
            SalarySet salarySet = salarySetMapper.selectOne(queryWrapper);
//            SalarySet salarySet = salarySetService.getById(employee.getId());
            //获取每个项目参与人员的基础薪资+交通补助+伙食补助
            System.out.println("salarySet是"+salarySet);
            if(salarySet!=null){
                employeeExt.setOriginalPay(salarySet.getBasicSalary()
                        .add(salarySet.getTrafficSubsidy())
                        .add(salarySet.getMealsSubsidy()));
                // 累加基础薪资
                totalOriginalPay = totalOriginalPay.add(salarySet.getBasicSalary()
                        .add(salarySet.getTrafficSubsidy())
                        .add(salarySet.getMealsSubsidy()));
            }
            System.out.println("累加薪资totalOriginalPay是"+totalOriginalPay);
            System.out.println("employeeExt.getOriginalPay是"+employeeExt.getOriginalPay());
            //获取每个项目参与人员的基础薪资
//            if(salary!=null){
//                employeeExt.setOriginalPay(salary.getOriginalPay());
//                // 累加基础薪资
//                totalOriginalPay = totalOriginalPay.add(salary.getOriginalPay());
//            }
            Position position = positionService.getById(employee.getPositionId());
            if(position!=null){
                employeeExt.setPosition(position.getPname());
            }
            Department department = departmentService.getById(employee.getDepartmentId());
            if(department!=null){
                employeeExt.setDepartmentName(department.getName());
            }
            employeesExt.add(employeeExt);
        }
        projectResourceExt.setEmployeesExt(employeesExt);
        projectResourceExt.setTotalOriginalPay(totalOriginalPay);
        //根据项目id查询到了这个项目用到什么工具
        List<ToolsExt> toolsExts = new ArrayList<>();
        BigDecimal totalValue = BigDecimal.ZERO; // 初始化totalValue为0
        for(ProjectToolAssignment projectToolAssignment : projectToolAssignmentList){
            //遍历这个项目的工具
            Tools tool = toolsService.getById(projectToolAssignment.getToolId());
            ToolsExt toolsExt =  new ToolsExt();
            BeanUtils.copyProperties(tool,toolsExt);
            //每个工具对应的需求数量
            toolsExt.setToolSQuantity(projectToolAssignment.getToolAssignmentQuantity());
            //每种工具总价
            BigDecimal totalPrice = tool.getPrice().multiply(BigDecimal.valueOf(projectToolAssignment.getToolAssignmentQuantity()));
            toolsExt.setTotalPrice(totalPrice);

            toolsExts.add(toolsExt);
            // 累加每次计算得出的totalPrice
            totalValue = totalValue.add(totalPrice);
        }
        //所有工具总价
//        BigDecimal totalValue =
        projectResourceExt.setTotalValue(totalValue);

        projectResourceExt.setToolsExt(toolsExts);


        //项目经理
        Employee employee = employeeService.getById(project.getEmployeeId());
        if(employee!=null){
            projectResourceExt.setEmployerName(employee.getName());
        }

        //项目所属部门
        Department department = departmentService.getById(project.getDepartmentId());
        if(department!=null) {
            projectResourceExt.setDepartmentName(department.getName());
        }
        //相关客户名
        Client client = clientService.getById(project.getClientId());
        if(client!=null) {
            projectResourceExt.setClientName(client.getName());
        }
        if (projectResourceExt!=null){
            return new Result(Code.SELECT_OK,projectResourceExt);
        }
        return new Result(Code.SELECT_ERR,projectResourceExt);
    }

    //项目名独一无二验证
    @GetMapping("/checkUniqueProjectName")
    public boolean checkUniqueProjectName(@RequestParam String projectName) {
        System.out.println("checkUniqueProjectName能生效吗"+projectName);
        LambdaQueryWrapper<Project> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Project::getProjectName, projectName);
        return projectMapper.selectCount(queryWrapper) == 0;
    }

    @GetMapping("/getPnameAndId")
    public Result getAllProjectsNameAndId(){//R<List<Project>>
        System.out.println("查询所有未分配负责人和员工的项目名字以及id");
        // 从数据库中检索所有项目名字

//        queryWrapper.select(Project::getId,Project::getProjectName);
//        List<Project> projectList = projectService.list(queryWrapper);

//筛选出 Project 表中 Id 属性不在 Participant 表中 project_id 属性集合中的记录
//        LambdaQueryWrapper<Project> queryWrapper = new LambdaQueryWrapper<>();
//        queryWrapper.notIn(Project::getId,
//                new LambdaQueryWrapper<Participant>().select(Participant::getProjectId));
//-------------------------
        List<Long> projectIdsInParticipant = participantMapper.selectList(
                        new LambdaQueryWrapper<Participant>().select(Participant::getProjectId))
                .stream()
                .map(Participant::getProjectId)
                .collect(Collectors.toList());

        LambdaQueryWrapper<Project> queryWrapper = new LambdaQueryWrapper<>();
        if (!projectIdsInParticipant.isEmpty()) {
            queryWrapper.notIn(Project::getId, projectIdsInParticipant);
        }

        List<Project> projectList = projectMapper.selectList(queryWrapper);

        System.out.println("getPnameAndId项目有"+projectList);
        if(projectList!=null){//查出来才返回@PathVariable Long id
            return new Result(Code.SELECT_OK,projectList,"查询项目成功");//R.success(projectsNames);
        }
        return new Result(Code.SELECT_ERR,"项目名字为空");
    }

    @GetMapping("/getProjectIdAndName")
    public Result getProjectIdAndName(@RequestParam("id") String id){
        System.out.println("当前登录用户的id是"+id);
        LambdaQueryWrapper<Project> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Project::getEmployeeId,id)//queryWrapper.ge  表示"大于等于"
                .ge(Project::getEndDate,new Date());// 截止时间晚于当前时间的记录(项目未结束)
        List<Project> projectList = projectMapper.selectList(queryWrapper);

        if (projectList != null) {
            return new Result(Code.SELECT_OK,projectList,"负责的项目查询成功");
        } else {
            return new Result(Code.SELECT_ERR,"该员工没有负责的项目");
//            return Long.valueOf(0);
        }
    }

    //被分配到项目的员工，登录时，可以给该项目的员工分配任务
    @GetMapping("/getAllproject")
    public Result getAllProjects(){
        LambdaQueryWrapper<Project> queryWrapper = new LambdaQueryWrapper<>();
//        queryWrapper.le(Project::getEndDate, new Date()); // 筛选出截止时间早于当前时间的记录
        //queryWrapper.gt  表示"大于"（greater than）
        queryWrapper.gt(Project::getEndDate, new Date()); // 截止时间晚于当前时间的记录(项目未结束)
        List<Project> projectList = projectMapper.selectList(queryWrapper);
        System.out.println("截止时间晚于当前时间的记录："+projectList);
        if(projectList!=null){
            return new Result(Code.SELECT_OK,projectList,"在保项目记录查询成功");
        }
        return new Result(Code.SELECT_ERR,"在保项目记录查询失败");
    }


    @PutMapping("/updateProject")
    public Result update(@RequestBody Project project){
//‘@RequestBody’注释表明‘Projects’对象将从请求体中反序列化，通常采用JSON或XML格式。
        System.out.println("修改项目信息："+project);

        long id = Thread.currentThread().getId();
        System.out.println("当前线程id为：{}" + id);
        projectService.updateById(project);//updateById继承自父接口IService(由mybatis-plus提供)
        return new Result(Code.UPDATE_OK,"项目信息修改成功");
    }

    //新增项目
    @PostMapping("/addProject")
    public Result save(@RequestBody Project project){
        System.out.println("新增项目，项目信息是："+project);
        projectService.save(project);//把这个对象存进去
        Client client = clientService.getById(project.getClientId());
        client.setStatus(1);//把合作状态设为1
        clientService.updateById(client);//更新到数据库
//save方法继承自mybatis-plus的父接口IService（看看application.yml文件）,可以直接调用
        return new Result(Code.SAVE_OK,"新增项目成功，已变更客户合作状态");
    }

}
